fix(snapshots): Show 'Waiting for base' instead of 'Base' when base artifact not found#115446
Conversation
…ha exists but base artifact not found
|
🚨 Warning: This pull request contains Frontend and Backend changes! It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently. Have questions? Please ask in the |
📊 Type Coverage Diff✅ No new type safety issues introduced. Coverage: 93.50% |
…l type The comparison_state field was being set to "waiting_for_base" but the Pydantic Literal type only allowed "pending", "processing", "success", and "failed", which would cause a ValidationError at runtime. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 57342fa. Configure here.
…exists When a comparison record exists in PENDING/PROCESSING/FAILED state, the base artifact was already found. Showing "waiting_for_base" in that case is misleading — fall through to "solo" and let the run_info carry the actual comparison state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ng base (#115448) When a head snapshot uploads before its base build (e.g., due to network timing), the status check task immediately posts a FAILURE to GitHub with "No base snapshots found." This is a false negative — the base just hasn't arrived yet. This adds a grace period: instead of failing immediately, the task posts an IN_PROGRESS status ("Waiting for base snapshots...") and schedules a delayed self-invocation (10 minutes). If the base arrives before the timeout, the existing comparison flow re-triggers the status check which takes the normal path — the timeout task becomes a harmless no-op. If the base never arrives, the timeout flips it to FAILURE. The approach is event-driven rather than poll-based: no retries, no new state to maintain. The task re-runs the same idempotent logic and queries the DB for current truth. Companion to #115446 which adds the matching "Waiting for base" UI state in the frontend. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
There is no valid scenario where a snapshot uploaded as part of a PR should lack a base SHA — without it, the server cannot identify which base build to compare against. Previously this was silently accepted, leading to orphaned "solo" snapshots that could never produce diffs. This adds client-side validation that bails early with an actionable error message before any images are uploaded or API calls are made. The error points users to either pass `--base-sha` explicitly or ensure their CI environment exposes the merge base. Companion to getsentry/sentry#115446, getsentry/sentry#115448, and getsentry/sentry#115460 which handle the server/UI side of base-build edge cases.

When a snapshot is uploaded with a
base_shabut no matching base artifact exists yet, both the snapshot list and detail pages incorrectly show a "Base" badge — implying the build is a base build with no comparison intended. In reality, the upload explicitly requested a comparison but the base hasn't been uploaded yet.This changes both the list and detail APIs to return a
waiting_for_basestate whenbase_shais present but no base artifact or comparison exists. The frontend now shows a "Waiting for base" tag with a tooltip explaining the build will resolve within ~10 minutes or fail.Backend:
comparison_type): returns"waiting_for_base"instead of"solo"whenbase_shaexists but no comparison manifest foundcomparison_state): returns"waiting_for_base"instead ofnullwhenbase_shaexists but noPreprodSnapshotComparisonrecord foundSnapshotComparisonInfoPydantic model: added"waiting_for_base"to thecomparison_stateLiteral type to preventValidationErrorat runtimeFrontend:
<Tag variant="muted">Waiting for base</Tag>with tooltipisSoloViewtreatswaiting_for_basethe same assolofor rendering purposes